﻿using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Threading.Tasks;
using VisionCloud.Core.Model.Ms;
using VisionCloud.Domain.Common;
using VisionCloud.Domain.DtoModel.Schedule.ProjectInfo;
using VisionCloud.Domain.Repository.Interface.Ms;
using VisionCloud.Domain.UnitOfWork;
using VisionCloud.Service.Fms;

namespace VisionCloud.Service.Schedule
{
    public class ProjectExternalService
    {
        public IMsProjectBuildingRepository MsProjectBuildingRepository { get; set; }

        public IMsProjectRepository MsProjectRepository { set; get; }

        public ILogger<ProjectExternalService> Logger { set; get; }

        public ProjectDCService ProjectDCService { set; get; }

        public IUnitOfWork UnitOfWork { get; set; }

        public async Task<ApiResult> AddOrUpdateProjectInfo(string fmsProjectCode)
        {
            var fmsProjectInfo = await ProjectDCService.GetFmsProjectInfos(fmsProjectCode);
            if (fmsProjectInfo == null) return new ApiResult { Code = AjaxCode.Fail, Message = $"该FMS项目{fmsProjectCode}不存在" };
            return await AddOrUpdateProjectInfo(fmsProjectInfo);
        }

        public async Task<ApiResult> AddOrUpdateProjectInfo(ProjectSyncFmsDto fmsProjectInfo)
        {
            var project = await MsProjectRepository.FirstOrDefaultAsync(x => x.MapProjectId == fmsProjectInfo.MapProjectId && !x.IsDeleted);
            return project != null ? await UpdateProjectInfo() : await AddProjectInfo(fmsProjectInfo);

            #region 本地函数:更新项目信息

            async Task<ApiResult> UpdateProjectInfo()
            {
                var updateFlag = false;
                try
                {
                    var projectId = project.ProjectId;
                    if (project.LastUpdatedDate < fmsProjectInfo.updatedTime)
                    {
                        var (lat, longt) = SplitCenter(fmsProjectInfo.center);
                        project.LastUpdatedDate = fmsProjectInfo.updatedTime.Value;
                        project.fmsProjectCode = fmsProjectInfo.projectCode;
                        project.fmsProjectName = fmsProjectInfo.projectName;
                        project.bdcProjectCode = fmsProjectInfo.bdcProjectCode;
                        project.bdcProjectName = fmsProjectInfo.bdcProjectName;
                        project.Latitude = lat;
                        project.Longitude = longt;
                        project.Address = fmsProjectInfo.location;
                        project.Province = fmsProjectInfo.provinceName;
                        project.City = fmsProjectInfo.cityName;
                        project.Town = fmsProjectInfo.districtName;
                        MsProjectRepository.Update(project);
                        updateFlag = true;
                    }

                    var buildings = await MsProjectBuildingRepository.WhereAsNoTrackingAsync(x => x.ProjectId == projectId && !x.IsDeleted);
                    fmsProjectInfo.Buildings?.ForEach(fmsBuilding =>
                    {
                        var building = buildings?.First(x => x.fmsBuildingCode == fmsBuilding.buildingCode);
                        if (building == null)
                        {
                            //新增楼栋
                            AddProjectBuilding(fmsBuilding, projectId, fmsProjectInfo.projectCode);
                            updateFlag = true;
                        }
                        else if (fmsBuilding.updatedTime.HasValue && building?.LastUpdatedDate < fmsBuilding.updatedTime)
                        {
                            //更新楼栋
                            building.BuildingName = fmsBuilding.buildingName;
                            building.TotalFloors = fmsBuilding.totalFloors;
                            building.LastUpdatedDate = fmsBuilding.updatedTime.Value;
                            building.fmsBuildingName = fmsBuilding.buildingName;
                            building.bdcBuildingCode = fmsBuilding.bdcBuildingCode;
                            building.bdcBuildingName = fmsBuilding.bdcBuildingName;
                            MsProjectBuildingRepository.Update(building);
                            updateFlag = true;
                        }
                    });
                    var result = new ApiResult(AjaxCode.Success, "成功");
                    if (updateFlag)
                    {
                        var dbRows = await UnitOfWork.SaveChangesAsync();
                        if (dbRows == 0)
                        {
                            result.Code = AjaxCode.Error;
                            result.Message = "更新项目信息失败";
                        }
                    }
                    return result;
                }
                catch (Exception ex)
                {
                    return new ApiResult { Code = AjaxCode.Error, Message = $"{ex.Message}\\innerException:{ex.InnerException.Message}" };
                }
            }

            #endregion 本地函数:更新项目信息
        }

        public async Task<ApiResult> AddProjectInfo(ProjectSyncFmsDto projectInfo)
        {
            try
            {
                var projectId = Guid.NewGuid();
                var projectNo = projectInfo.projectCode;
                var (lat, longt) = SplitCenter(projectInfo.center);
                MsProjectRepository.Add(new MsProject
                {
                    ProjectId = projectId,
                    DataSource = 1,
                    Name = projectInfo.projectName,
                    ProjectNo = projectNo,
                    Province = projectInfo.provinceName,
                    City = projectInfo.cityName,
                    Town = projectInfo.districtName,
                    Address = projectInfo.location,
                    Description = "从FMS同步",
                    Latitude = lat,
                    Longitude = longt,
                    MapProjectId = projectInfo.MapProjectId,
                    fmsProjectName = projectInfo.projectName,
                    fmsProjectCode = projectNo,
                    bdcProjectCode = projectInfo.bdcProjectCode,
                    bdcProjectName = projectInfo.bdcProjectName,
                    CreatedDate = projectInfo.createdTime,
                    LastUpdatedDate = projectInfo.updatedTime ?? projectInfo.createdTime,
                });

                projectInfo.Buildings?.ForEach(fmsProjectBuilding => AddProjectBuilding(fmsProjectBuilding, projectId, projectNo));

                var dbRows = await UnitOfWork.SaveChangesAsync();

                return dbRows > 0 ? new ApiResult { Code = AjaxCode.Success, Message = "成功" } : new ApiResult { Code = AjaxCode.Error, Message = "新增项目信息失败" };
            }
            catch (Exception ex)
            {
                return new ApiResult { Code = AjaxCode.Error, Message = $"{ex.Message}\\innerException:{ex.InnerException.Message}" };
            }
        }

        private void AddProjectBuilding(ProjectBuilding fmsProjectBuilding, Guid projectId, string projectCode)
        {
            MsProjectBuildingRepository.Add(new MsProjectBuilding
            {
                Id = Guid.NewGuid(),
                ProjectId = projectId,
                ProjectNo = projectCode,
                BuildingName = fmsProjectBuilding.buildingName,
                TotalFloors = fmsProjectBuilding.totalFloors,
                CreatedDate = fmsProjectBuilding.createdTime,
                LastUpdatedDate = fmsProjectBuilding.updatedTime ?? fmsProjectBuilding.createdTime,
                fmsBuildingCode = fmsProjectBuilding.buildingCode,
                fmsBuildingName = fmsProjectBuilding.buildingName,
                bdcBuildingCode = fmsProjectBuilding.bdcBuildingCode,
                bdcBuildingName = fmsProjectBuilding.buildingName,
            });
        }

        private (double, double) SplitCenter(string center)
        {
            double latitude = 0;
            double longitude = 0;
            var arr = center?.Split(',');
            if (arr?.Length > 1)
            {
                double.TryParse(arr[0]?.Trim(), out longitude);
                double.TryParse(arr[1]?.Trim(), out latitude);
            }
            return (latitude, longitude);
        }
    }
}